package com.wonders.frame.aspect;

import com.alibaba.fastjson.JSON;
import com.gcr.server.response.Response;
import com.wonders.frame.common.Enum.RemovedCodeEnum;
import com.wonders.frame.common.Enum.SessionKeyEnum;
import com.wonders.frame.common.util.ServerUtil;
import com.wonders.frame.entity.AuthAccount;
import com.wonders.frame.entity.AuthLog;
import com.wonders.frame.repository.AuthLogRepository;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Objects;

/**
 * @author qiu
 * @date 2019-10-17 15:14
 */
@Aspect
@Component
public class WebRequestLogAspect {

    private static Logger logger = LoggerFactory.getLogger(WebRequestLogAspect.class);

    @Autowired
    private AuthLogRepository authLogRepository;

    /*@Pointcut("within(com.wonders.nyffbz.controller.LoginController)" +
            "|| within(com.wonders.nyffbz.controller.AuthAccountController)" +
            "|| within(com.wonders.nyffbz.controller.AuthRoleController)"
    )*/
    @Pointcut("execution(* com.wonders.frame.controller..*.*(..)) " +
            "&&!execution(* com.wonders.frame.controller.VerifyController.*(..))" +
            "&&!execution(* com.wonders.frame.controller.CommonSourceController.*(..))"+
            "&&!execution(* com.wonders.frame.controller.AuthDicController.getAuthDicMap(..))"+
            "&&!execution(* com.wonders.frame.controller.AuthLogController.*(..))"


    )
    public void webRequestLog() {}

    @Before("webRequestLog()")
    public void doBefore(JoinPoint joinPoint) {
        try {
            // 接收到请求，记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if(StringUtils.isEmpty(attributes)){
                return;
            }
            HttpServletRequest request = attributes.getRequest();

            HttpSession session=request.getSession();
            AuthAccount acc =  (AuthAccount)session.getAttribute(SessionKeyEnum.USERINFO.name());


            String beanName = joinPoint.getSignature().getDeclaringTypeName();
            String methodName = joinPoint.getSignature().getName();
            String uri = request.getRequestURI();
            String remoteAddr = ServerUtil.getIpAddr(request);
            String method = request.getMethod();
            String params = "";
            if ("POST".equals(method)) {
                Object[] paramsArray = joinPoint.getArgs();
                params = argsArrayToString(paramsArray);
            } else {
                params = request.getQueryString();
                if(!StringUtils.isEmpty(params)){
                    params=params.replace("&",";");
                }
            }

            AuthLog authLog=new AuthLog();

            if (!StringUtils.isEmpty(acc)&&!StringUtils.isEmpty(acc.getAccount())){
                authLog.setAccount(acc.getAccount());
                authLog.setAccountName(acc.getUser().getUserName());
            }


            authLog.setExecuteDate(new Date());
            authLog.setIp(remoteAddr);
            authLog.setMethodType(method);
            authLog.setParams(params);
            authLog.setUrl(uri);
            authLog.setRemoved(RemovedCodeEnum.AVAILABLE.getCode());

            whatExecuteType(authLog);
            authLogRepository.save(authLog);
            logger.info("beanName=" + beanName +"; uri=" + uri +" ; methodName=" + methodName +  "; remoteAddr=" + remoteAddr + "; method="+method+ "; params{" + params+"}");

        } catch (Exception e) {
            logger.info("操作请求日志记录失败doBefore()", e);
        }
    }

    //@AfterReturning(returning="object",value = "webRequestLog()")
    public void doAfter(JoinPoint joinPoint,Object object){
        try {
            Response response=(Response)object;
            // 接收到请求，记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if(StringUtils.isEmpty(attributes)){
                return;
            }
            HttpServletRequest request = attributes.getRequest();

            HttpSession session=request.getSession();
            AuthAccount acc =  (AuthAccount)session.getAttribute(SessionKeyEnum.USERINFO.name());


            String beanName = joinPoint.getSignature().getDeclaringTypeName();
            String methodName = joinPoint.getSignature().getName();
            String uri = request.getRequestURI();
            String remoteAddr = ServerUtil.getIpAddr(request);
            String method = request.getMethod();
            String params = "";
            if ("POST".equals(method)) {
                Object[] paramsArray = joinPoint.getArgs();
                params = argsArrayToString(paramsArray);
            } else {
                params = request.getQueryString();
                if(!StringUtils.isEmpty(params)){
                    params=params.replace("&",";");
                }
            }

            AuthLog authLog=new AuthLog();

            if (!StringUtils.isEmpty(acc)&&!StringUtils.isEmpty(acc.getAccount())){
                authLog.setAccount(acc.getAccount());
                authLog.setAccountName(acc.getUser().getUserName());
            }


            authLog.setExecuteDate(new Date());
            authLog.setIp(remoteAddr);
            authLog.setMethodType(method);
            authLog.setParams(params);
            authLog.setUrl(uri);
            authLog.setRemoved(RemovedCodeEnum.AVAILABLE.getCode());

            whatExecuteType(authLog);
            authLogRepository.save(authLog);
            logger.info("beanName=" + beanName +"; uri=" + uri +" ; methodName=" + methodName +  "; remoteAddr=" + remoteAddr + "; method="+method+ "; params{" + params+"}");

        } catch (Exception e) {
            logger.info("操作请求日志记录失败doBefore()", e);
        }
    }


    public void whatExecuteType(AuthLog authLog){
        if(Objects.equals(authLog.getUrl(),"/login")){
            authLog.setExecuteType("登录");
        }else if(Objects.equals(authLog.getUrl(),"/loginOut")){
            authLog.setExecuteType("登出");
        }else if(Objects.equals(authLog.getUrl(),"/authAccount/resetPassword")){
            authLog.setExecuteType("重置密码");
        }else if(Objects.equals(authLog.getUrl(),"/authAccount/updatePassword")){
            authLog.setExecuteType("修改密码");
        }else if(Objects.equals(authLog.getUrl(),"/authAccount/unlock")){
            authLog.setExecuteType("解锁");
        }else if(Objects.equals(authLog.getUrl(),"/authRole/updateRolePermission")){
            authLog.setExecuteType("用户赋权");
        }else if(Objects.equals(authLog.getUrl(),"/authAccount/accountLogout")){
            authLog.setExecuteType("注销");
        }else if(Objects.equals(authLog.getUrl(),"/authAccount/accountEnable")){
            authLog.setExecuteType("启用");
        }else if(authLog.getUrl().contains("save")){
            authLog.setExecuteType("新增/修改");
        }else if(authLog.getUrl().contains("get")||authLog.getUrl().contains("find")){
            authLog.setExecuteType("查询");
        }else if(authLog.getUrl().contains("delete")||authLog.getUrl().contains("Delete")){
            authLog.setExecuteType("删除");
        }
    }

    /**
     * 请求参数拼装
     *
     * @param paramsArray
     * @return
     */
    private String argsArrayToString(Object[] paramsArray) {
        String params = "";
        if (paramsArray.length >= 0) {
            Object jsonObj = JSON.toJSON(paramsArray[0]);
            if(!StringUtils.isEmpty(jsonObj)){
                params += jsonObj.toString();
            }

            /*for (int i = 0; i < paramsArray.length; i++) {
                Object jsonObj = JSON.toJSON(paramsArray[i]);
                params += jsonObj.toString() + " ";
            }*/
        }
        return params.trim();
    }

}